pub mod iroh_wrapper;
pub mod rig_routes;
pub mod database;
pub mod content_routes;
pub mod vector_search;

use std::sync::Arc;

use axum::extract::State;
use axum::http::StatusCode;
use axum::routing::{delete, get, post, put};
use axum::{Json, Router};
use rig_app::{AgentManager, ToolManager};

use crate::iroh_wrapper::{IrohInfo, IrohNodeWrapper};
use crate::database::DatabaseManager;
use serde::{Deserialize, Serialize};

// Import the send_message function from iroh-app
use iroh_app::send_message;

// Define the application state
#[derive(Clone)]
pub struct AppState {
    pub agent_manager: Arc<AgentManager>,
    pub tool_manager: Arc<ToolManager>,
    pub iroh_node: Arc<IrohNodeWrapper>,
    pub database: Arc<DatabaseManager>,
}

pub fn create_axum_app(
    agent_manager: Arc<AgentManager>,
    tool_manager: Arc<ToolManager>,
    iroh_node: Arc<IrohNodeWrapper>,
    database: Arc<DatabaseManager>,
) -> Router {
    let state = AppState {
        agent_manager,
        tool_manager,
        iroh_node,
        database,
    };

    Router::new()
        // Agent management routes
        .route("/api/agents", post(rig_routes::create_agent_handler))
        .route("/api/agents", get(rig_routes::list_agents_handler))
        .route("/api/agents/{id}", get(rig_routes::get_agent_handler))
        .route("/api/agents/{id}", delete(rig_routes::delete_agent_handler))
        // MCP service management routes
        .route(
            "/api/mcp/services",
            post(rig_routes::create_mcp_service_handler),
        )
        .route(
            "/api/mcp/services",
            get(rig_routes::list_mcp_services_handler),
        )
        .route(
            "/api/mcp/services/{id}",
            get(rig_routes::get_mcp_service_handler),
        )
        .route(
            "/api/mcp/services/{id}",
            delete(rig_routes::delete_mcp_service_handler),
        )
        .route("/api/tools", get(rig_routes::list_mcp_tools_handler))
        .route(
            "/api/tools/{tool_name}/run",
            post(rig_routes::execute_mcp_tool_handler),
        )
        // Chat functionality routes
        .route("/api/rig/prompt", post(rig_routes::prompt_handler))
        .route(
            "/api/agents/{agent_name}/chat",
            post(rig_routes::chat_handler),
        )
        .route(
            "/api/rig/stream-chat",
            post(rig_routes::stream_chat_handler),
        )
        // Iroh routes
        .route("/api/iroh/status", get(iroh_status))
        .route("/api/iroh/join", post(join_iroh_node))
        .route("/api/iroh/close", post(close_iroh_node))
        .route("/api/iroh/send", post(send_message_handler))
        // Conversation routes
        .route("/api/conversations", post(content_routes::create_conversation_handler))
        .route("/api/conversations", get(content_routes::list_conversations_handler))
        .route("/api/conversations/{id}", get(content_routes::get_conversation_handler))
        .route("/api/conversations/{id}", put(content_routes::update_conversation_handler))
        .route("/api/conversations/{id}", delete(content_routes::delete_conversation_handler))
        // Message routes
        .route("/api/conversations/{id}/messages", post(content_routes::create_message_handler))
        .route("/api/conversations/{id}/messages", get(content_routes::get_messages_handler))
        .route("/api/messages/{id}", put(content_routes::update_message_handler))
        // Bookmark routes
        .route("/api/bookmarks", post(content_routes::create_bookmark_handler))
        .route("/api/bookmarks", get(content_routes::list_bookmarks_handler))
        .route("/api/bookmarks/search", get(content_routes::search_bookmarks_handler))
        .route("/api/bookmarks/{id}", get(content_routes::get_bookmark_handler))
        .route("/api/bookmarks/{id}", delete(content_routes::delete_bookmark_handler))
        .route("/api/bookmarks/{id}/use", post(content_routes::use_bookmark_handler))
        .route("/api/bookmarks/{id}/favorite", post(content_routes::toggle_bookmark_favorite_handler))
        // Knowledge routes
        .route("/api/knowledge", post(content_routes::create_knowledge_item_handler))
        .route("/api/knowledge", get(content_routes::list_knowledge_items_handler))
        .route("/api/knowledge/search", get(content_routes::search_knowledge_items_handler))
        .route("/api/knowledge/search/vector", get(content_routes::vector_search_knowledge_items_handler))
        .route("/api/knowledge/search/fts", get(content_routes::fts_search_knowledge_items_handler))
        .route("/api/knowledge/{id}", get(content_routes::get_knowledge_item_handler))
        .route("/api/knowledge/{id}", delete(content_routes::delete_knowledge_item_handler))
        // Enhanced knowledge routes with vector support
        .route("/api/knowledge/vector", post(content_routes::create_knowledge_item_with_vector_handler))
        .route("/api/knowledge/{id}/vector", put(content_routes::update_knowledge_item_with_vector_handler))
        .route("/api/knowledge/{id}/vector", delete(content_routes::delete_knowledge_item_with_vector_handler))
        .route("/api/knowledge/batch", post(content_routes::batch_create_knowledge_items_handler))
        .with_state(Arc::new(state))
}

// Handler for /api/iroh/send
pub async fn send_message_handler(
    State(_state): State<Arc<AppState>>,
    Json(request): Json<SendMessageRequest>,
) -> Result<Json<IrohOperationResponse>, StatusCode> {
    let text = request.text;
    let target_node_id = request.target_node_id;

    // Call the send_message function from iroh-app
    match send_message(text, target_node_id).await {
        Ok(_) => Ok(Json(IrohOperationResponse {
            success: true,
            message: "Message sent successfully".to_string(),
        })),
        Err(e) => Ok(Json(IrohOperationResponse {
            success: false,
            message: format!("Failed to send message: {}", e),
        })),
    }
}

// Request body for /api/iroh/send
#[derive(Debug, Deserialize)]
pub struct SendMessageRequest {
    text: String,
    target_node_id: Option<String>,
}

// Handler for /api/iroh/status
#[axum::debug_handler]
pub async fn iroh_status(
    State(_state): State<Arc<AppState>>,
) -> Result<Json<IrohStatusResponse>, StatusCode> {
    let is_running = _state.iroh_node.is_node_running();

    let node_info = if is_running {
        match _state.iroh_node.get_node_info().await {
            Ok(info) => Some(info),
            Err(_) => None,
        }
    } else {
        None
    };

    Ok(Json(IrohStatusResponse {
        is_running,
        node_info,
    }))
}

// Request body for /api/iroh/join
#[derive(Debug, Deserialize)]
pub struct JoinTicketRequest {
    ticket: String,
}

// Handler for /api/iroh/join
pub async fn join_iroh_node(
    State(_state): State<Arc<AppState>>,
    Json(request): Json<JoinTicketRequest>,
) -> Result<Json<IrohOperationResponse>, StatusCode> {
    let ticket = request.ticket;
    match _state.iroh_node.join_node(ticket).await {
        Ok(_) => Ok(Json(IrohOperationResponse {
            success: true,
            message: "Iroh node joined successfully".to_string(),
        })),
        Err(e) => Ok(Json(IrohOperationResponse {
            success: false,
            message: format!("Failed to join Iroh node: {}", e),
        })),
    }
}

// Handler for /api/iroh/close
pub async fn close_iroh_node(
    State(_state): State<Arc<AppState>>,
) -> Result<Json<IrohOperationResponse>, StatusCode> {
    _state.iroh_node.close_node().await;
    Ok(Json(IrohOperationResponse {
        success: true,
        message: "Iroh node closed successfully".to_string(),
    }))
}

// Response for Iroh status
#[derive(Serialize)]
pub struct IrohStatusResponse {
    pub is_running: bool,
    pub node_info: Option<IrohInfo>,
}

// Response for Iroh operations (join, close)
#[derive(Serialize)]
pub struct IrohOperationResponse {
    success: bool,
    message: String,
}
